package cn.pconline.officialclub.service;

import cn.pconline.autoclub.config.SystemConfig;
import cn.pconline.autoclub.entity.User;
import cn.pconline.autoclub.service.BaseService;
import cn.pconline.autoclub.service.PagerService;
import cn.pconline.autoclub.util.Pager;
import cn.pconline.officialclub.entity.EntityWithClub;
import cn.pconline.officialclub.entity.EntityWithUser;
import cn.pconline.officialclub.entity.OClub;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import org.gelivable.dao.GeliDao;
import org.gelivable.dao.GeliOrm;
import org.gelivable.dao.SqlBuilder;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.dao.DataAccessException;
import org.springframework.dao.EmptyResultDataAccessException;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.jdbc.core.ResultSetExtractor;

/**
 * service帮助类，注意，要很通用的才放这里
 *
 * 约定，本包的service都继承此帮助类。尽量用本类提供的方法。
 *
 * 主要是对：geli提供的查询方法做了包装，处理了空结果异常，提供一些相对简短的方法调用
 *
 * 方法命名：方法名不需要加O做为前缀，除了参数的oClubId需要区别，其他的不需要区别
 *
 * @author <a href="mailto:chensy0203@163.com">chensy</a>
 */
public abstract class ServiceKit extends BaseService {

    @Autowired
    protected GeliDao geliDao;
    @Autowired
    private GeliOrm geliOrm;
    @Autowired
    protected SystemConfig systemConfig;
    @Autowired
    protected PagerService pagerService;
    @Autowired
    protected JdbcTemplate jdbcTemplate;
    protected static final Logger log = LoggerFactory.getLogger(ServiceKit.class);

    /**
     * 比geli多了空异常的捕获
     *
     * @param <T>
     * @param type
     * @param id
     * @return
     */
    public <T> T findById(java.lang.Class<T> type, Object id) {
        try {
            return geliDao.find(type, id);
        } catch (EmptyResultDataAccessException e) {
            return null;
        }
    }

    /**
     * 比geli多了空异常的捕获
     *
     * @param <T>
     * @param type
     * @param id
     * @return
     */
    public <T> T findById(java.lang.Class<T> type, long x, Object id) {
        try {
            return geliDao.find(type, x, id);
        } catch (EmptyResultDataAccessException e) {
            return null;
        }
    }

    /**
     * 比geli多了空异常的捕获
     *
     * @param <T>
     * @param type
     * @param sql
     * @return
     */
    protected <T> java.util.List<T> list(java.lang.Class<T> type, SqlBuilder sql) {
        try {
            return geliDao.list(type, sql.getSql(), sql.getValues());
        } catch (EmptyResultDataAccessException e) {
            return Collections.emptyList();
        }
    }

    /**
     * 比geli多了空异常的捕获
     *
     * @param <T>
     * @param type
     * @param x
     * @param sql
     * @return
     */
    protected <T> java.util.List<T> list(java.lang.Class<T> type, long x, SqlBuilder sql) {
        try {
            return geliDao.list(type, x, sql.getSql(), sql.getValues());
        } catch (EmptyResultDataAccessException e) {
            return Collections.emptyList();
        }
    }

    /**
     * 比geli多了空异常的捕获
     *
     * @param <T>
     * @param type
     * @param ids
     * @return
     */
    public <T> java.util.List<T> list(java.lang.Class<T> type, Object... ids) {
        try {
            return geliDao.list(type, ids);
        } catch (EmptyResultDataAccessException e) {
            return Collections.emptyList();
        }
    }

    /**
     * 比geli多了空异常的捕获
     *
     * @param <T>
     * @param type
     * @param ids
     * @return
     */
    public <T> java.util.List<T> list(java.lang.Class<T> type, long x, Object... ids) {
        try {
            return geliDao.list(type, x, ids);
        } catch (EmptyResultDataAccessException e) {
            return Collections.emptyList();
        }
    }

    /**
     * 实际调用page方法，写第一页
     *
     * @param <T>
     * @param type
     * @param x
     * @param sql
     * @return
     */
    protected <T> java.util.List<T> listLimit(java.lang.Class<T> type, SqlBuilder sql, int limit) {
        try {
            return geliDao.page(type, sql.getSql(), 1, limit, sql.getValues());
        } catch (EmptyResultDataAccessException e) {
            return Collections.emptyList();
        }
    }

    /**
     * 比geli多了空异常的捕获
     *
     * @param <T>
     * @param type
     * @param x
     * @param sql
     * @return
     */
    protected <T> java.util.List<T> listLimit(java.lang.Class<T> type, long x, SqlBuilder sql, int limit) {
        try {
            return geliDao.page(type, x, sql.getSql(), 1, limit, sql.getValues());
        } catch (EmptyResultDataAccessException e) {
            return Collections.emptyList();
        }
    }

    /**
     * 比geli多了空异常的捕获
     *
     * @param sql
     * @return
     */
    protected int count(SqlBuilder sql) {
        try {
            return geliDao.count(sql.getSql(), sql.getValues());
        } catch (EmptyResultDataAccessException e) {
            return 0;
        }
    }

    /**
     * 直接操作数据库，适合不需要缓存的
     *
     * @param sql
     * @return
     */
    protected int update(SqlBuilder sql) {
        try {
            return jdbcTemplate.update(sql.getSql(), sql.getValues());
        } catch (EmptyResultDataAccessException e) {
            return 0;
        }
    }

    protected <T> T findFirst(java.lang.Class<T> type, SqlBuilder sql) {
        return geliDao.findFirst(type, sql.getSql(), sql.getValues());
    }

    protected <T> T findFirst(java.lang.Class<T> type, long x, SqlBuilder sql) {
        return geliDao.findFirst(type, sql.getSql(), x, sql.getValues());
    }

    public boolean isNotEmpty(Pager pager) {
        return pager != null && pager.getResultList() != null && !pager.getResultList().isEmpty();
    }

    /**
     * 批量load用户
     *
     * @param pager
     */
    public void loadUsers(Pager<? extends EntityWithUser> pager) {
        if (isNotEmpty(pager)) {
            pager.setResultList(loadUsers(pager.getResultList()));
        }
    }

    /**
     * 批量load用户
     *
     * @param entities
     * @return
     */
    public List loadUsers(List<? extends EntityWithUser> entities) {
        if (entities == null || entities.isEmpty()) {
            return entities;
        }
        long[] ids = new long[entities.size()];
        for (int i = 0; i < entities.size(); i++) {
            EntityWithUser entity = entities.get(i);
            if (entity != null) {
                ids[i] = entity.getUserId();
            }
        }
        List<User> users = geliDao.list(User.class, ids);
        for (int i = 0; i < entities.size(); i++) {
            EntityWithUser entity = entities.get(i);
            if (entity != null) {
                entity.setUser(users.get(i));
            }
        }
        return entities;
    }
    /**
     * 批量load用户
     *
     * @param entities
     * @return
     */
    public List loadClub(List<? extends EntityWithClub> entities) {
        if (entities == null || entities.isEmpty()) {
            return entities;
        }
        long[] ids = new long[entities.size()];
        for (int i = 0; i < entities.size(); i++) {
            EntityWithClub entity = entities.get(i);
            if (entity != null) {
                ids[i] = entity.getoClubId();
            }
        }
        List<OClub> oClubs = geliDao.list(OClub.class, ids);
        for (int i = 0; i < entities.size(); i++) {
            EntityWithClub entity = entities.get(i);
            if (entity != null) {
                entity.setoClub(oClubs.get(i));
            }
        }
        return entities;
    }
    /**
     * 根据Sql查出id列表
     *
     * @param sql （认为第一列是id）
     * @return
     */
    protected List<Long> getIds(SqlBuilder sql) {
        List<Long> list = jdbcTemplate.query(sql.getSql(), sql.getValues(), new ResultSetExtractor<List<Long>>() {
            @Override
            public List<Long> extractData(ResultSet rs) throws SQLException, DataAccessException {
                List<Long> list = new ArrayList();
                while (rs.next()) {
                    long id = rs.getLong(1);
                    list.add(id);
                }
                return list;
            }
        });
        return list;
    }

    /**
     * 获取表名
     *
     * @param type
     * @return
     */
    protected String getTableName(java.lang.Class type) {
        return geliOrm.getTableName(type);
    }

    /**
     * 获取分表表名
     *
     * @param type
     * @return
     */
    protected String getTableName(java.lang.Class type, long x) {
        return geliOrm.getTableName(type, x);
    }
}
